package com.utils.web.spring;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;

/**
 * 日志过滤器
 */
@Aspect
@Component
@Slf4j
public class Log2Filter {

	private static final ObjectMapper mapper = new ObjectMapper();

	private long startTimeMillis;

	private long endTimeMillis;
	
	private String URI;

	@Pointcut("execution(* com.kyhd.small.controller.*.*(..))")
	public void controller() {
	}

	@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
	public void requestMapping() {
	}

	@Before("controller()")
	public void doBefore(JoinPoint joinPoint) {
		startTimeMillis = System.currentTimeMillis();
		org.springframework.web.context.request.RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes sra = (ServletRequestAttributes) ra;
		HttpServletRequest request = sra.getRequest();
		//log.info("Token=[ {} ]", new Object[] { request.getHeader("Token") });
		URI = request.getRequestURI();
		printMap(URI, request.getParameterMap());
	}

	@After("controller()")
	public void doAfter(JoinPoint joinPoint) {
		endTimeMillis = System.currentTimeMillis();
        log.info("URI:{} completed response time:{}",URI,endTimeMillis-startTimeMillis);
	}

	@AfterReturning(pointcut = "controller()", returning = "returnValue")
	public JoinPoint afterReturning(JoinPoint joinPoint, Object returnValue) {
		org.springframework.web.context.request.RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes sra = (ServletRequestAttributes) ra;
		@SuppressWarnings("unused")
		HttpServletRequest request = sra.getRequest();
		return joinPoint;
	}

	@AfterThrowing(pointcut = "controller()", throwing = "e")
	public void afterThrowing(Throwable e) {
	}

	private void printMap(String prefix, @SuppressWarnings("rawtypes") Map map) {
		StringBuilder buf = new StringBuilder();
		for (Object o : map.entrySet()) {
			@SuppressWarnings("rawtypes")
			Map.Entry entry = (Map.Entry) o;
			buf.append((String) entry.getKey());
			buf.append("=");
			try {
				buf.append(mapper.writeValueAsString(entry.getValue()));
				buf.append(",");
			} catch (IOException e) {

			}
		}
		log.info("URI:{},Parameter:({})",prefix,buf);
	}
}
